#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
import collections

Card = collections.namedtuple('Card',['rank','suit'])

class FrenchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')
    suits = 'spades diamonds clubs hearts'.split()

    def __init__(self):
        # 作用是: 生成一个按花色分组的52张牌的列表,其中每个花色各有13张不同点数的牌.
        self._cards = [Card(rank,suit) for suit in self.suits 
                                        for rank in self.ranks]

    def __len__(self):
        return len(self._cards)
    
    def __getitem__(self,position):
        return self._cards[position]

beer_card = Card('7','diamonds')
print(beer_card)
'''
用collections.namedtuple构建了一个简单类来表示一张纸牌.
namedtuple用以构建只有少数属性但是没有方法的对象.
'''    

# 用len()函数查看一叠牌有多少张
deck = FrenchDeck()
print(len(deck))
# 抽取特定一张纸牌,deck[0]和deck[-1]由__getitem__方法提供.
print(deck[0])
print(deck[-1])

# 内置函数random.choice,从一个序列中随机选出一个元素.
from random import choice
print(choice(deck))
print(choice(deck))
print(choice(deck))

# 因为__getitem__方法把[]操作交给了self._cards操作,deck类自动支持切片操作.
# 先抽出索引是12的那张牌,然后每隔13张牌拿1张
print(deck[:3])
print(deck[12::13])

# 仅实现了__getitem__方法,这一摞牌就可迭代
for card in deck:
    print(card)

# 反向迭代
for card in reversed(deck):
    print(card)

# 迭代通常是隐式的,in运算符可以用在FrenchDeck类上,是可迭代的.
print(Card('Q','hearts') in deck)
print(Card('7','beasts') in deck)

print('====='*20)
'''
排序:
用点数来判定扑克牌的大小,2最小, A最大;同时还要加上对花色的判定,黑桃最大,红桃次之,方块再次,梅花最小.
梅花2的大小是0,黑桃A是51
'''
suit_values = dict(spades=3,hearts=2,diamonds=1,clubs=0)
def spades_high(card):
    rank_value = FrenchDeck.ranks.index(card.rank)
    return rank_value * len(suit_values) + suit_values[card.suit]

# 对这摞牌进行升序排序:
for card in sorted(deck,key=spades_high):
    print(card)

'''
FrenchDeck隐式地继承了object类.功能不是继承而来的. 
通过实现__len__和__getitem__这两个特殊方法,FrenchDeck就跟一个Python自有的序列数据类型一样.
Python3默认继承object.
'''
"""

# 1. 一个简单的二维向量类
from math import hypot

class Vector:
    def __init__(self,x=0,y=0):
        self.x = x
        self.y = y
    
    def __repr__(self):
        return 'Vector(%r,%r)' %(self.x,self.y)
    
    def __abs__(self):
        return hypot(self.x,self.y)

    def __bool__(self):
        return bool(abs(self))   

    def __add__(self,other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x,y)
    
    def __mul__(self,scalar):
        return Vector(self.x * scalar, self.y * scalar)
    